#include <avr/io.h>
#include <avr/interrupt.h>

typedef enum
{
	preflight,
	ascent,
	heating,
	cooling,
	shutdown
} STATES;

enum NETWORK_ID
{
	MESSAGE_OK		= 0b00000001,
	MESSAGE_ERROR	= 0b00000010,
	MESSAGE_DATA	= 0b00000100,
	MESSAGE_EVENT	= 0b00001000,
	MESSAGE_STAGE	= 0b00010000
};

int timerCounter16bit = 0;
int state = preflight;					//Set start state to pre-flight
uint8_t runMainLoop = 0;				//Set to one when Main loop should run
int LOcounter = 0;

/*
	Initializes the 8bit and 16bit timers, and sets their corresponding breaktimes aswell as enabling their interrupts
*/
void inittimer()
{
	//8-bit timer setup
	TCCR2A |= 1<<WGM21;							//Timer will restart when reaching specific value (OCR2A)
	TCCR2B |= 1<<CS22 | 1<<CS21 | 1<<CS20;		//Prescaler set to 1024 (1MHz -> 976.5625 ticks/s)
	TIMSK2 |= 1<<OCIE2A;						//Enable interrupt
	OCR2A = 98;									//Timer lookup value
	
	//16-bit timer setup
	TCCR1B |= 1<<CS10  | 1<<CS11 | 1<<WGM12;	//Prescaler set to 64 (1MHz -> 15625 ticks/sec)
	TCNT1 = 0x0000;								//Clear 16-bit timer (set as pre-launch timer)
	TIMSK1 |= 1<<OCIE1A;						//Enable interrupt
	OCR1A = 62499;								//62499 = 4 sec
	
	changeState(preflight);
}

uint16_t getTimer()
{
	return TCNT1;
}

uint16_t getTimerCounter()
{
	return timerCounter16bit;
}

void resettimercounter()
{
	timerCounter16bit = 0;
}

void changeState(STATES newState)
{
	state = newState;
	char tempState[1];
	tempState[0] = (char)newState;
	UART_SEND(MESSAGE_STAGE, &tempState[0], 1);
};

ISR(TIMER1_COMPA_vect)
{
	timerCounter16bit++;
}

/*
	This interrupt will trigger every 100ms (10Hz).
	It checks if it is time for a stage change and
	also triggers the mainloop which sends and stores
	data.
*/
ISR(TIMER2_COMPA_vect)
{
	//reset_wdt();
	switch(state)
	{
		case preflight:
			PORTB |= 1 << PINB1;
			UART_SEND(MESSAGE_OK,0,0);
			if (bit_is_set(PINC, 5))								//Check for 'LO' and count to 1 sec to avoid unwanted voltage peaks, Should be done by interrupt
			{
				LOcounter++;
			}
			else
			{
				LOcounter = 0;
			}
			if (LOcounter == 30)
			{
				TCNT1 = 0x0000;										//Reset 16-bit timer (set as post-launch timer)
				resettimercounter();								
				changeState(ascent);								//Change the state to Ascent and signal state change through UART
			}
			break;
		case ascent:
			PORTB |= 1 << PINB2;
			runMainLoop = 1;
			if (TCNT1 > 30000 && timerCounter16bit == 2)			//Time condition to start melting
			{
				changeState(heating);
			}
			break;
		case heating:
			PORTB |= 1 << PINB0;
			runMainLoop = 1;
			PORTB |= 1 << PINB6;//TEST								//Activate resistance wires (switch 1)
			PORTB |= 1 << PINB7;//TEST								//Activate resistance wires (switch 2)		
			if (TCNT1 > 15000 && timerCounter16bit == 6)			//Time condition to start cooling								
			//if (TCNT1 > 30000 && timerCounter16bit == 2)			//Time condition to start cooling
			{
				changeState(cooling);
			}
			break;
		case cooling:
			PORTD |= 1 << PIND7;
			runMainLoop = 1;
			PORTB &= ~(1 << PINB6);										//Deactivate resistance wires (switch 1)
			PORTB &= ~(1 << PINB7);										//Deactivate resistance wires (switch 2)
			if (TCNT1 > 0 && timerCounter16bit >= 10)				//Time condition to shut down
			//if (TCNT1 > 45000 && timerCounter16bit == 6)			//Time condition to shut down
			{
				changeState(shutdown);
			}
			break;
		case shutdown:
			PORTB = 0x00;
			PORTD = 0x00;
			//Shut down system
			break;
		default:
			//UART SEND ERROR
			break;
	}
}